package org.bridgen.runtime.model;

import org.bridgen.runtime.RecoveryHelper;
import org.bridgen.runtime.util.Interval;


/**
 * Default layout start island implementation.
 * 
 * @author Emma Söderberg <emma add cs.lth.se>
 *
 */

public abstract class LayoutStartIsland extends StartIsland {

	/**
	 * Creates a new LayoutEndIsland
	 * @param previous The previous node in the token list
	 * @param interval The corresponding interval
	 * @param value The corresponding value
	 */
	public LayoutStartIsland(LexicalNode previous, Interval interval, String value) {
		super(previous, interval, value);
	}

	/*
	 * (non-Javadoc)
	 * @see org.briplib.recovery.Island#bridgeMatch(org.briplib.recovery.Island, int)
	 */
	@Override
	public boolean bridgeMatch(Island target, int tol) {
		if (isEndIsland(target))  {
			LayoutEndIsland end = (LayoutEndIsland)target;
			LayoutStartIsland start = this;
			return end.indent() != null && 
				this.indent() != null && 
				end.indent().pos() == start.indent().pos();
		}
		return false;
	}

	
	/*
	 * (non-Javadoc)
	 * @see org.briplib.recovery.Island#insertFakeIsland(org.briplib.recovery.Island, org.briplib.recovery.LexicalNode)
	 */
	/*
	@Override
	public void insertFakeIsland(Island island, LexicalNode node) {
		if (island.isFake()) {
			RecoveryHelper.insertBefore(island, node);
		}
	}
	*/

	/*
	 * (non-Javadoc)
	 * @see org.briplib.recovery.Island#possibleConstructionSite(org.briplib.recovery.LexicalNode)
	 */
	@Override
	public boolean possibleConstructionSite(LexicalNode node) {
		if (isLayoutReef(node)) {
			LayoutReef reef = (LayoutReef)node;
			if (indent() != null && (reef.pos() < indent().pos() && 
					!(isEndIsland(reef.getNext())) 
					|| reef.pos() == indent().pos())) {
				Island newIsland = constructFakeIsland(node, false);
				RecoveryHelper.insertBefore(newIsland, node);
				newIsland.buildBridge(this, -1);
				return true;
			}
		}
		else if (isEndIsland(node)) {
			LayoutEndIsland island = (LayoutEndIsland)node;
			if (indent() != null && (!island.hasBridge() && 
					island.indent().pos() < indent().pos())) {
				Island newIsland = constructFakeIsland(node, false);
				RecoveryHelper.insertBefore(newIsland, node);
				newIsland.buildBridge(this, -1);
				return true;
			}
		}
		return false; 
	}


	/**
	 * Checks if a node is a layout reef
	 * @param node The node to check
	 * @return true if there's a match
	 */
	protected boolean isLayoutReef(LexicalNode node) {
		return node instanceof LayoutReef;
	}
	
	
	/**
	 * Checks if the given node is a matching end island
	 * @param node The node to check
	 * @return true if there's a match
	 */
	protected boolean isEndIsland(LexicalNode node) {
		return node instanceof LayoutEndIsland;
	}

	
	/*
	 * Attribute: LayoutReef LayoutStartIsland.indent
	 */
	private LayoutReef indent;
	public LayoutReef indent() {
		if (indent == null) {
			indent = (LayoutReef)getPreviousOfType(LayoutReef.class);
		}
		return indent;
	}
	
	
	private LayoutReef indent_compute() {
		// Left/Right
		LexicalNode pos = getPrevious();
		// Ordering
		int order = 2;
		int hits = 1;
		while (pos != null && hits <= order) {
			// Left/Right/Type
			Object find = pos.getPreviousOfType(LayoutReef.class);
			if (find == null)
				pos = null;
			else if (hits == order) {
				// Type
				return (LayoutReef)find;
			} else {
				hits++;
				// Type/Left/Right
				pos = ((LayoutReef)find).getPrevious();
			}
		}
		return null;
	}
}
